using Microsoft.Extensions.Logging;
using System.Globalization;
using System.Text;
using System.Web;
using Uantek.Model.Mas;

namespace Uantek.Device.Communication.Utilities
{
    /// <summary>
    /// 连接字符串构建器
    /// </summary>
    public class ConnectionStringBuilder
    {
        /// <summary>
        /// 日志记录器
        /// </summary>
        private readonly ILogger<ConnectionStringBuilder>? _logger;

        /// <summary>
        /// 连接参数字典
        /// </summary>
        private readonly Dictionary<string, object> _parameters = new();

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="logger">日志记录器</param>
        public ConnectionStringBuilder(ILogger<ConnectionStringBuilder>? logger = null)
        {
            _logger = logger;
        }

        /// <summary>
        /// 构造函数（从连接字符串初始化）
        /// </summary>
        /// <param name="connectionString">连接字符串</param>
        /// <param name="logger">日志记录器</param>
        public ConnectionStringBuilder(string connectionString, ILogger<ConnectionStringBuilder>? logger = null)
        {
            _logger = logger;
            ParseConnectionString(connectionString);
        }

        /// <summary>
        /// 设置参数
        /// </summary>
        /// <param name="key">参数键</param>
        /// <param name="value">参数值</param>
        /// <returns>当前实例</returns>
        public ConnectionStringBuilder SetParameter(string key, object value)
        {
            if (string.IsNullOrWhiteSpace(key))
            {
                _logger?.LogWarning("参数键不能为空");
                return this;
            }

            _parameters[key] = value;
            _logger?.LogDebug("设置连接参数: {Key} = {Value}", key, value);
            return this;
        }

        /// <summary>
        /// 获取参数
        /// </summary>
        /// <typeparam name="T">参数类型</typeparam>
        /// <param name="key">参数键</param>
        /// <param name="defaultValue">默认值</param>
        /// <returns>参数值</returns>
        public T GetParameter<T>(string key, T defaultValue = default!)
        {
            if (string.IsNullOrWhiteSpace(key))
            {
                return defaultValue;
            }

            if (_parameters.TryGetValue(key, out var value))
            {
                try
                {
                    return ConvertValue<T>(value);
                }
                catch (Exception ex)
                {
                    _logger?.LogWarning(ex, "参数类型转换失败: {Key} = {Value}", key, value);
                    return defaultValue;
                }
            }

            return defaultValue;
        }

        /// <summary>
        /// 移除参数
        /// </summary>
        /// <param name="key">参数键</param>
        /// <returns>当前实例</returns>
        public ConnectionStringBuilder RemoveParameter(string key)
        {
            if (!string.IsNullOrWhiteSpace(key) && _parameters.Remove(key))
            {
                _logger?.LogDebug("移除连接参数: {Key}", key);
            }
            return this;
        }

        /// <summary>
        /// 清空所有参数
        /// </summary>
        /// <returns>当前实例</returns>
        public ConnectionStringBuilder Clear()
        {
            _parameters.Clear();
            _logger?.LogDebug("清空所有连接参数");
            return this;
        }

        /// <summary>
        /// 设置TCP连接参数
        /// </summary>
        /// <param name="host">主机地址</param>
        /// <param name="port">端口</param>
        /// <param name="connectTimeout">连接超时（毫秒）</param>
        /// <param name="receiveTimeout">接收超时（毫秒）</param>
        /// <param name="sendTimeout">发送超时（毫秒）</param>
        /// <returns>当前实例</returns>
        public ConnectionStringBuilder SetTcpParameters(string host, int port, int connectTimeout = 5000, 
            int receiveTimeout = 5000, int sendTimeout = 5000)
        {
            SetParameter("Host", host);
            SetParameter("Port", port);
            SetParameter("ConnectTimeout", connectTimeout);
            SetParameter("ReceiveTimeout", receiveTimeout);
            SetParameter("SendTimeout", sendTimeout);
            SetParameter("TransportType", "TCP");
            return this;
        }

        /// <summary>
        /// 设置UDP连接参数
        /// </summary>
        /// <param name="host">主机地址</param>
        /// <param name="port">端口</param>
        /// <param name="localPort">本地端口</param>
        /// <param name="enableBroadcast">启用广播</param>
        /// <param name="receiveTimeout">接收超时（毫秒）</param>
        /// <param name="sendTimeout">发送超时（毫秒）</param>
        /// <returns>当前实例</returns>
        public ConnectionStringBuilder SetUdpParameters(string host, int port, int localPort = 0, 
            bool enableBroadcast = false, int receiveTimeout = 5000, int sendTimeout = 5000)
        {
            SetParameter("Host", host);
            SetParameter("Port", port);
            SetParameter("LocalPort", localPort);
            SetParameter("EnableBroadcast", enableBroadcast);
            SetParameter("ReceiveTimeout", receiveTimeout);
            SetParameter("SendTimeout", sendTimeout);
            SetParameter("TransportType", "UDP");
            return this;
        }

        /// <summary>
        /// 设置串口连接参数
        /// </summary>
        /// <param name="portName">端口名称</param>
        /// <param name="baudRate">波特率</param>
        /// <param name="dataBits">数据位</param>
        /// <param name="stopBits">停止位</param>
        /// <param name="parity">校验位</param>
        /// <param name="readTimeout">读取超时（毫秒）</param>
        /// <param name="writeTimeout">写入超时（毫秒）</param>
        /// <returns>当前实例</returns>
        public ConnectionStringBuilder SetSerialParameters(string portName, int baudRate = 9600, 
            int dataBits = 8, string stopBits = "One", string parity = "None", 
            int readTimeout = 5000, int writeTimeout = 5000)
        {
            SetParameter("PortName", portName);
            SetParameter("BaudRate", baudRate);
            SetParameter("DataBits", dataBits);
            SetParameter("StopBits", stopBits);
            SetParameter("Parity", parity);
            SetParameter("ReadTimeout", readTimeout);
            SetParameter("WriteTimeout", writeTimeout);
            SetParameter("TransportType", "Serial");
            return this;
        }

        /// <summary>
        /// 设置Modbus TCP参数
        /// </summary>
        /// <param name="host">主机地址</param>
        /// <param name="port">端口</param>
        /// <param name="unitId">单元标识符</param>
        /// <param name="timeout">超时时间（毫秒）</param>
        /// <returns>当前实例</returns>
        public ConnectionStringBuilder SetModbusTcpParameters(string host, int port = 502, byte unitId = 1, int timeout = 5000)
        {
            SetTcpParameters(host, port, timeout, timeout, timeout);
            SetParameter("UnitId", unitId);
            SetParameter("ProtocolType", "ModbusTCP");
            return this;
        }

        /// <summary>
        /// 设置Modbus RTU参数
        /// </summary>
        /// <param name="portName">端口名称</param>
        /// <param name="baudRate">波特率</param>
        /// <param name="slaveId">从站地址</param>
        /// <param name="dataBits">数据位</param>
        /// <param name="stopBits">停止位</param>
        /// <param name="parity">校验位</param>
        /// <param name="timeout">超时时间（毫秒）</param>
        /// <returns>当前实例</returns>
        public ConnectionStringBuilder SetModbusRtuParameters(string portName, int baudRate = 9600, 
            byte slaveId = 1, int dataBits = 8, string stopBits = "One", string parity = "None", int timeout = 5000)
        {
            SetSerialParameters(portName, baudRate, dataBits, stopBits, parity, timeout, timeout);
            SetParameter("SlaveId", slaveId);
            SetParameter("ProtocolType", "ModbusRTU");
            return this;
        }

        /// <summary>
        /// 从设备参数构建连接字符串
        /// </summary>
        /// <param name="parameter">设备参数</param>
        /// <returns>当前实例</returns>
        public ConnectionStringBuilder FromEquipmentParameter(MasEquipmentParameter parameter)
        {
            if (parameter == null)
            {
                _logger?.LogWarning("设备参数为空");
                return this;
            }

            try
            {
                // 设置基本参数
                if (!string.IsNullOrWhiteSpace(parameter.ProtocolType))
                {
                    SetParameter("ProtocolType", parameter.ProtocolType);
                }

                if (!string.IsNullOrWhiteSpace(parameter.CommunicateOption))
                {
                    SetParameter("CommunicateOption", parameter.CommunicateOption);
                }

                if (!string.IsNullOrWhiteSpace(parameter.DataAddr))
                {
                    ParseDataAddress(parameter.DataAddr);
                }

                if (parameter.PeriodTime.HasValue)
                {
                    SetParameter("PeriodTime", parameter.PeriodTime.Value);
                }

                if (!string.IsNullOrWhiteSpace(parameter.DataType))
                {
                    SetParameter("DataType", parameter.DataType);
                }

                if (!string.IsNullOrWhiteSpace(parameter.DataExpression))
                {
                    SetParameter("DataExpression", parameter.DataExpression);
                }

                if (!string.IsNullOrWhiteSpace(parameter.Command))
                {
                    ParseCommand(parameter.Command);
                }

                _logger?.LogDebug("从设备参数构建连接字符串完成: {ParameterId}", parameter.Id);
            }
            catch (Exception ex)
            {
                _logger?.LogError(ex, "从设备参数构建连接字符串时发生异常: {ParameterId}", parameter?.Id);
            }

            return this;
        }

        /// <summary>
        /// 构建连接字符串
        /// </summary>
        /// <returns>连接字符串</returns>
        public string Build()
        {
            try
            {
                if (_parameters.Count == 0)
                {
                    return string.Empty;
                }

                var sb = new StringBuilder();

                // 获取协议类型和传输类型
                var protocolType = GetParameter<string>("ProtocolType", "");
                var transportType = GetParameter<string>("TransportType", "");

                // 构建基础URL
                if (!string.IsNullOrWhiteSpace(protocolType))
                {
                    sb.Append($"{protocolType.ToLower()}://");
                }
                else if (!string.IsNullOrWhiteSpace(transportType))
                {
                    sb.Append($"{transportType.ToLower()}://");
                }

                // 构建主机和端口部分
                BuildHostPortPart(sb);

                // 构建查询参数部分
                BuildQueryPart(sb);

                var result = sb.ToString();
                _logger?.LogDebug("构建连接字符串完成: {ConnectionString}", result);
                return result;
            }
            catch (Exception ex)
            {
                _logger?.LogError(ex, "构建连接字符串时发生异常");
                return string.Empty;
            }
        }

        /// <summary>
        /// 获取连接参数字典
        /// </summary>
        /// <returns>连接参数字典</returns>
        public Dictionary<string, object> GetParameters()
        {
            return new Dictionary<string, object>(_parameters);
        }

        /// <summary>
        /// 检查是否包含参数
        /// </summary>
        /// <param name="key">参数键</param>
        /// <returns>是否包含</returns>
        public bool HasParameter(string key)
        {
            return !string.IsNullOrWhiteSpace(key) && _parameters.ContainsKey(key);
        }

        /// <summary>
        /// 获取所有参数键
        /// </summary>
        /// <returns>参数键集合</returns>
        public IEnumerable<string> GetParameterKeys()
        {
            return _parameters.Keys;
        }

        /// <summary>
        /// 复制参数到另一个构建器
        /// </summary>
        /// <param name="target">目标构建器</param>
        /// <returns>当前实例</returns>
        public ConnectionStringBuilder CopyTo(ConnectionStringBuilder target)
        {
            if (target != null)
            {
                foreach (var kvp in _parameters)
                {
                    target.SetParameter(kvp.Key, kvp.Value);
                }
            }
            return this;
        }

        #region 私有方法

        /// <summary>
        /// 解析连接字符串
        /// </summary>
        /// <param name="connectionString">连接字符串</param>
        private void ParseConnectionString(string connectionString)
        {
            try
            {
                if (string.IsNullOrWhiteSpace(connectionString))
                {
                    return;
                }

                var uri = new Uri(connectionString);

                // 解析协议
                if (!string.IsNullOrWhiteSpace(uri.Scheme))
                {
                    SetParameter("ProtocolType", uri.Scheme);
                }

                // 解析主机和端口
                if (!string.IsNullOrWhiteSpace(uri.Host))
                {
                    SetParameter("Host", uri.Host);
                }

                if (uri.Port > 0)
                {
                    SetParameter("Port", uri.Port);
                }

                // 解析路径（可能是串口名称）
                if (!string.IsNullOrWhiteSpace(uri.LocalPath) && uri.LocalPath != "/")
                {
                    var path = uri.LocalPath.TrimStart('/');
                    if (path.StartsWith("COM", StringComparison.OrdinalIgnoreCase) || 
                        path.StartsWith("/dev/", StringComparison.OrdinalIgnoreCase))
                    {
                        SetParameter("PortName", path);
                    }
                }

                // 解析查询参数
                if (!string.IsNullOrWhiteSpace(uri.Query))
                {
                    var query = HttpUtility.ParseQueryString(uri.Query);
                    foreach (string key in query.AllKeys)
                    {
                        if (!string.IsNullOrWhiteSpace(key))
                        {
                            var value = query[key];
                            if (!string.IsNullOrWhiteSpace(value))
                            {
                                SetParameter(key, ParseValue(value));
                            }
                        }
                    }
                }

                _logger?.LogDebug("连接字符串解析完成: {ConnectionString}", connectionString);
            }
            catch (Exception ex)
            {
                _logger?.LogError(ex, "解析连接字符串时发生异常: {ConnectionString}", connectionString);
            }
        }

        /// <summary>
        /// 解析数据地址
        /// </summary>
        /// <param name="dataAddr">数据地址</param>
        private void ParseDataAddress(string dataAddr)
        {
            if (string.IsNullOrWhiteSpace(dataAddr))
            {
                return;
            }

            // 尝试解析为URI格式
            try
            {
                if (dataAddr.Contains("://"))
                {
                    var uri = new Uri(dataAddr);
                    SetParameter("Host", uri.Host);
                    if (uri.Port > 0)
                    {
                        SetParameter("Port", uri.Port);
                    }
                }
                else
                {
                    // 尝试解析为主机:端口格式
                    var parts = dataAddr.Split(':');
                    if (parts.Length == 2)
                    {
                        SetParameter("Host", parts[0]);
                        if (int.TryParse(parts[1], out var port))
                        {
                            SetParameter("Port", port);
                        }
                    }
                    else
                    {
                        // 可能是串口名称或其他地址格式
                        SetParameter("Address", dataAddr);
                    }
                }
            }
            catch
            {
                SetParameter("Address", dataAddr);
            }
        }

        /// <summary>
        /// 解析命令
        /// </summary>
        /// <param name="command">命令</param>
        private void ParseCommand(string command)
        {
            if (string.IsNullOrWhiteSpace(command))
            {
                return;
            }

            SetParameter("Command", command);

            // 尝试解析命令中的参数
            try
            {
                if (command.Contains("="))
                {
                    var parts = command.Split(';', '&');
                    foreach (var part in parts)
                    {
                        var keyValue = part.Split('=');
                        if (keyValue.Length == 2)
                        {
                            var key = keyValue[0].Trim();
                            var value = keyValue[1].Trim();
                            if (!string.IsNullOrWhiteSpace(key) && !string.IsNullOrWhiteSpace(value))
                            {
                                SetParameter(key, ParseValue(value));
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                _logger?.LogWarning(ex, "解析命令参数时发生异常: {Command}", command);
            }
        }

        /// <summary>
        /// 解析值
        /// </summary>
        /// <param name="value">字符串值</param>
        /// <returns>解析后的值</returns>
        private static object ParseValue(string value)
        {
            if (string.IsNullOrWhiteSpace(value))
            {
                return value;
            }

            // 尝试解析为数字
            if (int.TryParse(value, out var intValue))
            {
                return intValue;
            }

            if (double.TryParse(value, out var doubleValue))
            {
                return doubleValue;
            }

            // 尝试解析为布尔值
            if (bool.TryParse(value, out var boolValue))
            {
                return boolValue;
            }

            return value;
        }

        /// <summary>
        /// 构建主机端口部分
        /// </summary>
        /// <param name="sb">字符串构建器</param>
        private void BuildHostPortPart(StringBuilder sb)
        {
            var host = GetParameter<string>("Host", "");
            var port = GetParameter<int>("Port", 0);
            var portName = GetParameter<string>("PortName", "");

            if (!string.IsNullOrWhiteSpace(host))
            {
                sb.Append(host);
                if (port > 0)
                {
                    sb.Append($":{port}");
                }
            }
            else if (!string.IsNullOrWhiteSpace(portName))
            {
                sb.Append(portName);
            }
        }

        /// <summary>
        /// 构建查询参数部分
        /// </summary>
        /// <param name="sb">字符串构建器</param>
        private void BuildQueryPart(StringBuilder sb)
        {
            var queryParams = new List<string>();

            foreach (var kvp in _parameters)
            {
                // 跳过已经在URL中使用的参数
                if (kvp.Key == "ProtocolType" || kvp.Key == "TransportType" || 
                    kvp.Key == "Host" || kvp.Key == "Port" || kvp.Key == "PortName")
                {
                    continue;
                }

                var value = FormatValue(kvp.Value);
                if (!string.IsNullOrWhiteSpace(value))
                {
                    queryParams.Add($"{HttpUtility.UrlEncode(kvp.Key)}={HttpUtility.UrlEncode(value)}");
                }
            }

            if (queryParams.Count > 0)
            {
                sb.Append("?");
                sb.Append(string.Join("&", queryParams));
            }
        }

        /// <summary>
        /// 格式化值
        /// </summary>
        /// <param name="value">值</param>
        /// <returns>格式化后的字符串</returns>
        private static string FormatValue(object value)
        {
            if (value == null)
            {
                return string.Empty;
            }

            if (value is bool boolValue)
            {
                return boolValue.ToString().ToLower();
            }

            if (value is double doubleValue)
            {
                return doubleValue.ToString(CultureInfo.InvariantCulture);
            }

            if (value is float floatValue)
            {
                return floatValue.ToString(CultureInfo.InvariantCulture);
            }

            return value.ToString() ?? string.Empty;
        }

        /// <summary>
        /// 转换值类型
        /// </summary>
        /// <typeparam name="T">目标类型</typeparam>
        /// <param name="value">值</param>
        /// <returns>转换后的值</returns>
        private static T ConvertValue<T>(object value)
        {
            if (value is T directValue)
            {
                return directValue;
            }

            if (typeof(T).IsEnum && value is string stringValue)
            {
                return (T)Enum.Parse(typeof(T), stringValue, true);
            }

            return (T)Convert.ChangeType(value, typeof(T), CultureInfo.InvariantCulture);
        }

        #endregion
    }
}